﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using NJamb.Parser.SpecificationBuilders.Delta.Singular;
using NJamb.Parser.SubjectBuilders;
using NJamb.Parser.Subjects.Singular;
using NJamb.Specifications.Delta;
using NJamb.Specifications.Simple.Singular;
using NUnit.Framework;
using Stile.NUnit;
using Stile.Patterns.SelfDescribingPredicates;
using Stile.Patterns.SelfDescribingPredicates.Evaluators;
using Stile.Readability;
using Stile.Testing.SampleTypes;
using Stile.Types;
#endregion

namespace NJamb.Tests.Specifications.Simple.Singular
{
    [TestFixture]
    public class SingularSpecificationFixture : SampleFixture
    {
        private Lazy<string> _lazyReason;
        private ISelfDescribingPredicate<int> _selfDescribingPredicate;
        private ISingularSubject<int> _subject;
        private SingularSpecification<int> _testSubject;

        [Test]
        public void AndLater()
        {
            // arrange
            const int i = -1;
            Assert.That(i, Is.Not.EqualTo(Sample.Default.Int), "precondition");
            ISingularSpecification<int> specification = Specify.For(() => _sample).That(x => x.Int).Is.EqualTo(Sample.Default.Int);
            var before = specification as SingularSpecification<int>;
            Assert.IsNotNull(before, "precondition");

            // act
            ISingularDeltaSpecificationBuilder<int> specificationBuilder = before.AndLater;
            IDeltaSpecification equalTo = specificationBuilder.Is.EqualTo(i);

            // assert
            var deltaSpecification = equalTo as DeltaSpecification<int>;
            Assert.IsNotNull(deltaSpecification);
            Assert.That(deltaSpecification.Before, Is.SameAs(specification));
            Assert.IsNotNull(deltaSpecification.After);
            var after = deltaSpecification.After as SingularSpecification<int>;
            Assert.IsNotNull(after);
            Assert.That(after.CollaboratingSubject, Is.SameAs(before.CollaboratingSubject));
            Assert.That(after.SelfDescribingPredicate, Is.Not.SameAs(before.SelfDescribingPredicate));
        }

        [Test]
        public void Because()
        {
            // arrange
            const string reason = "Throckmorton";

            // act
            var specification = _testSubject.Because(reason.ToLazy()) as SingularSpecification<int>;

            // assert
            Assert.IsNotNull(specification);
            IEvaluation evaluation = specification.Evaluate();
            StringAssert.Contains(reason, evaluation.Reason);
        }

        [Test]
        public void InitialValues()
        {
            Assert.That(_testSubject.LazyReason.IsValueCreated, Is.False);
            Assert.That(_testSubject.LazyReason, Is.SameAs(_lazyReason));
            Assert.That(_testSubject.SelfDescribingPredicate, Is.SameAs(_selfDescribingPredicate));
            Assert.That(_testSubject.CollaboratingSubject, Is.SameAs(_subject));
        }

        protected override void SetupComplete()
        {
            _subject = Specify.For(() => _sample).That(x => x.Int);
            _selfDescribingPredicate = new SimpleEvaluator<int>(-1, x => x == -1);
            _lazyReason = Null.String.ToLazy();
            _testSubject = new SingularSpecification<int>(_subject.Xray, _selfDescribingPredicate, _lazyReason);
        }
    }
}
